home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 130_01 / vfile.c < prev    next >
Text File  |  1985-03-09  |  9KB  |  266 lines

  1.   /***********************************************************\
  2.   *                                                           *
  3.   *   VFILE consists of 5 functions which simulate a "BASIC   *
  4.   *   RANDOM FILE" structure using fixed length records of    *
  5.   *   varying pre-specified size. A record may be up to 255   *
  6.   *   chars long. It is the programmer's responsibility to    *
  7.   *   keep track of the contents of his record, and VFILE's   *
  8.   *   responsibility to write and read the record to and from *
  9.   *   the correct position in file.  Record numbers are       *
  10.   *   maximum 32767. VFILE will give ERROR if reading past    *
  11.   *   end of file or exceeding legal bounds.  It will pad     *
  12.   *   as-yet-unwritten internal records with nulls. An error  *
  13.   *   is returned if there is not enough disk space for       *
  14.   *   either the record or the padding.  There is a sixth     *
  15.   *   function (vset), which is used internally.              *
  16.   *                                                           *
  17.   *   The structure "_vbuf" must be included in the           *
  18.   *   programme, and each file must reserve a VBUFSIZ area    *
  19.   *   for buffering.  This area will vary depending on NSECTS *
  20.   *   in BDSCIO.H   THE VALUE OF NSECTS MUST BE GREATER       *
  21.   *   THAN TWO.  The definitions of _vbuf and VBUFSIZ         *
  22.   *   should eventually find their way into BDSCIO.H          *
  23.   *   I have included them in this source for clarity.        *
  24.   *                                                           *
  25.   \************************************************************
  26.  
  27.  
  28.  
  29.  
  30.     Version 1.0  by Greg Lister
  31.  
  32.         19th November, 1980                */
  33.  
  34.  
  35.  
  36.  
  37. #include "bdscio.h"
  38. #define VBUFSIZ NSECTS * SECSIZ + 14
  39.  
  40. struct _vbuf
  41. {   int fd;    /* File Descriptor */
  42.     int eof;    /* Actual EOF of file */
  43.     int pos;    /* Current record's position in buffer */
  44.     int len;    /* Record length */
  45.     int sta;    /* Start sector of buffer */
  46.     int cnt;    /* Number of sectors in buffer */
  47.     int wflag;    /* flag set if buffer written to */
  48.     char buffer[NSECTS * SECSIZ];
  49. };
  50.  
  51.  
  52. vset(recno,vbuf)
  53.     int recno;
  54.     struct _vbuf *vbuf;
  55.     /************************************************\
  56.     *                                                *
  57.     *   Sets up buffer for random reads and writes.  *
  58.     *   Flushes buffer if necessary and fills buffer *
  59.     *   with required data. Sets pointer to beginning*
  60.     *   of r/w record.  Fills unwritten buffer with  *
  61.     *   nulls.  Returns ERROR if cannot flush or     *
  62.     *   if hard read error.  Returns NULL if         *
  63.     *   required buffer is not yet written. Returns  *
  64.     *   -2 if required sector (128 byte) is not yet  *
  65.     *   written. Else returns valid sectors in buf.  *
  66.     *                                                *
  67.     \************************************************/
  68. {
  69.    int tmp,blkno,bss,blkoff,secno,bufsec,endrec;
  70.  
  71.    blkno=recno>>7;        /* Block Number */
  72.  
  73.    bss=blkno*vbuf->len;        /* Block start Sector */
  74.  
  75.    blkoff=(recno%128)*vbuf->len;    /* Offset into Block */
  76.  
  77.    secno=bss+(blkoff>>7);    /* Sector # of start of rec */
  78.  
  79.    endrec=bss+((blkoff+vbuf->len-1)>>7);/* Sec# END of rec */
  80.  
  81.    bufsec=(secno/(NSECTS-2))*(NSECTS-2); /* Start sec of buf */
  82.  
  83.    vbuf->pos=vbuf->buffer+((secno-bufsec)<<7)+(blkoff%128);
  84.  
  85.    if(bufsec!=vbuf->sta)
  86.    {    if(vbuf->wflag)
  87.     {   seek(vbuf->fd,vbuf->sta,0);
  88.            if(write(vbuf->fd,vbuf->buffer,vbuf->cnt)<vbuf->cnt)
  89.         return ERROR;
  90.         if((tmp=tell(vbuf->fd))>vbuf->eof)
  91.         vbuf->eof=tmp;
  92.         vbuf->wflag=0;
  93.     }
  94.     if((vbuf->sta=bufsec)>vbuf->eof) return NULL;
  95.     seek(vbuf->fd,bufsec,0);
  96.     if((vbuf->cnt=read(vbuf->fd,vbuf->buffer,NSECTS))<0)
  97.         return ERROR;
  98.     if(vbuf->cnt!=NSECTS)
  99.         fillb(vbuf->buffer+(vbuf->cnt<<7),
  100.         vbuf->buffer+(NSECTS<<7),0,0);
  101.    }
  102.  
  103.    if(endrec-bufsec>=vbuf->cnt) return -2;
  104.    return vbuf->cnt;
  105. }
  106.  
  107.  
  108. vwrite(recno,vbuf,str)
  109.     int recno;
  110.     struct _vbuf *vbuf;
  111.     char *str;
  112.  
  113.     /********************************************************\
  114.     *                                                        *
  115.     *   Writes data at str to file vbuf at recno.  Pads file *
  116.     *    with NULLS if skipping unwritten sections of file.   *
  117.     *    Returns ERROR if full disk, unopened file etc        *
  118.     *    Returns ERROR if bad record #;  else returns OK      *
  119.     *                                                        *
  120.     \********************************************************/
  121.  
  122. {   int tmp,tmp1,tmp2;
  123.  
  124.     if(recno<0) return ERROR;
  125.     if((tmp=vset(recno,vbuf))==-1) return ERROR;
  126.       if(tmp==0)
  127.       { fillb(vbuf->buffer,NSECTS<<7,0,1);
  128.     seek(vbuf->fd,vbuf->eof,0);
  129.     while((vbuf->eof=tell(vbuf->fd))<vbuf->sta)
  130.     if(write(vbuf->fd,vbuf->buffer,1)>1) return ERROR;
  131.       }
  132.       movmem(str,vbuf->pos,vbuf->len);
  133.       tmp2=vbuf->buffer;
  134.       tmp1=(127+vbuf->pos-tmp2+vbuf->len)>>7;
  135.       if(tmp1>vbuf->cnt)
  136.     vbuf->cnt=tmp1;
  137.       vbuf->wflag=1;
  138.     return OK;
  139. }
  140.  
  141.  
  142. vread(recno,vbuf,str)
  143.     int recno;
  144.     struct _vbuf *vbuf;
  145.     char str[];
  146.  
  147.     /************************************************\
  148.     *                                                *
  149.     *   Reads record 'recno' from file to 'str'.     *
  150.     *   Returns ERROR if hard error (unopened        *
  151.     *   file etc) or if attempt is made to read      *
  152.     *   past current end of file.  Returns no of     *
  153.     *   secs read in.   ERROR if bad recno.          *
  154.     *                                                *
  155.     \************************************************/
  156.  
  157. {   int tmp;
  158.     if(recno<0) return ERROR;
  159.     tmp=vbuf->sta;
  160.     if(vset(recno,vbuf)<1)
  161.     {
  162.     vbuf->sta=tmp;
  163.     return ERROR;
  164.     }
  165.     movmem(vbuf->pos,str,vbuf->len);
  166.     return vbuf->cnt;
  167. }
  168.  
  169.  
  170. vclose(vbuf)
  171.    struct _vbuf *vbuf;
  172.  
  173.     /************************************************\
  174.     *                                                *
  175.     *   Closes file using vbuf.  Returns OK if       *
  176.     *   closed successfully.  ERROR if error.        *
  177.     *                                                *
  178.     \************************************************/
  179.  
  180. {   if(vbuf->wflag)
  181.     {    seek(vbuf->fd,vbuf->sta,0);
  182.     if(write(vbuf->fd,vbuf->buffer,vbuf->cnt)<0)
  183.         return ERROR;
  184.     }
  185.     return close(vbuf->fd);
  186. }
  187.  
  188.  
  189.  
  190. vopen(filename,vbuf,reclen)
  191.     int reclen;
  192.     char filename[];
  193.     struct _vbuf *vbuf;
  194.  
  195.     /************************************************\
  196.     *                                                *
  197.     *   Opens filename for v-format buffered io      *
  198.     *   Reclen is the specified record length        *
  199.     *   (may be up to 255 chars).  Vbuf is a         *
  200.     *   VBUFSIZ buffer ((128 * NSECTS)+14)           *
  201.     *   **NOTE** NSECTS must be 3 or more for this   *
  202.     *   file structure to work.                      *
  203.     *   Returns ERROR if reclen is out of range      *
  204.     *   or if open error occurs (ie file doesn't     *
  205.     *   exist - use vcreat)                          *
  206.     *                                                *
  207.     \************************************************/
  208.  
  209. {   if((vbuf->len=reclen)>255)return ERROR;
  210.     if(reclen<0) return ERROR;
  211.     if((vbuf->fd=open(filename,2))<0) return ERROR;
  212.     vbuf->sta=vbuf->cnt=-1;
  213.     vbuf->wflag=0;
  214.     vbuf->pos=vbuf->buffer;
  215.     vbuf->eof=telend(filename);
  216.     return vbuf->fd;
  217. }
  218.  
  219.  
  220. vcreat(filename,vbuf,reclen)
  221.     int reclen;
  222.     char filename[];
  223.     struct _vbuf *vbuf;
  224.     /************************************************\
  225.     *                                                *
  226.     *   Creates a file as vopen (see above)          *
  227.     *                                                *
  228.     \************************************************/
  229. {   fabort(creat(filename));
  230.     return vopen(filename,vbuf,reclen);
  231. }
  232.  
  233.  
  234. /****************************************************\
  235. *                             *
  236. *  The next function is general and not only a part  *
  237. *  of the VFILE package. It will tell you where the  *
  238. *  end of your file is to be found.             *
  239. *                             *
  240. \*